import subprocess
import re
import json
import socket
from flask import Blueprint, request, jsonify, current_app
import netifaces
from app.models.system import SystemLog

network_bp = Blueprint('network', __name__)

def get_ip_address():
    """获取主IP地址"""
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    try:
        # 不需要真正连接
        s.connect(('10.255.255.255', 1))
        ip = s.getsockname()[0]
    except Exception:
        ip = '127.0.0.1'
    finally:
        s.close()
    return ip

@network_bp.route('/interfaces', methods=['GET'])
def get_interfaces():
    """获取网络接口列表"""
    try:
        print("获取网络接口请求已接收")
        interfaces = []
        
        for iface in netifaces.interfaces():
            # 排除不需要显示的接口
            if (iface.startswith('lo') or           # 回环接口
                iface.startswith('veth') or         # Docker虚拟接口
                iface.startswith('br-') or          # Docker bridge
                iface == 'docker0'):               # Docker默认bridge
                continue
                
            addrs = netifaces.ifaddresses(iface)
            
            interface_info = {
                'name': iface,
                'mac': '',
                'ipv4': [],
                'ipv6': [],
                'active': False
            }
            
            # 获取MAC地址
            if netifaces.AF_LINK in addrs:
                interface_info['mac'] = addrs[netifaces.AF_LINK][0]['addr']
                
            # 获取IPv4地址
            if netifaces.AF_INET in addrs:
                for addr in addrs[netifaces.AF_INET]:
                    interface_info['ipv4'].append({
                        'address': addr.get('addr', ''),
                        'netmask': addr.get('netmask', ''),
                        'broadcast': addr.get('broadcast', '')
                    })
                    
            # 获取IPv6地址
            if netifaces.AF_INET6 in addrs:
                for addr in addrs[netifaces.AF_INET6]:
                    interface_info['ipv6'].append({
                        'address': addr.get('addr', ''),
                        'netmask': addr.get('netmask', '')
                    })
            
            # 检查接口状态
            interface_info['active'] = bool(interface_info['ipv4'] or interface_info['ipv6'])
            
            # 添加接口名称特性(有线/无线)
            if iface.startswith('wlan') or iface.startswith('wlp') or iface.startswith('wlP'):
                interface_info['type'] = 'wireless'
            elif iface.startswith('eth') or iface.startswith('enp') or iface.startswith('enP'):
                interface_info['type'] = 'ethernet'
            else:
                interface_info['type'] = 'other'
            
            interfaces.append(interface_info)
        
        return jsonify({'interfaces': interfaces, 'primary_ip': get_ip_address()})
        
    except Exception as e:
        SystemLog.log("ERROR", "network", f"获取网络接口失败: {str(e)}")
        return jsonify({'error': str(e)}), 500

@network_bp.route('/wifi/scan', methods=['GET'])
def scan_wifi():
    """扫描WiFi网络"""
    try:
        # 找出无线接口名
        wireless_iface = None
        for iface in netifaces.interfaces():
            # 支持更多无线接口名称格式：wlan, wlp, wlP
            if (iface.startswith('wlan') or 
                iface.startswith('wlp') or 
                iface.startswith('wlP')):
                wireless_iface = iface
                break
                
        if not wireless_iface:
            return jsonify({'error': 'No wireless interface found'}), 404
        
        # 使用nmcli扫描WiFi
        cmd = ['nmcli', '-t', '-f', 'SSID,SIGNAL,SECURITY', 'device', 'wifi', 'list', '--rescan', 'yes']
        process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        stdout, stderr = process.communicate()
        
        if process.returncode != 0:
            # 尝试使用iwlist
            cmd = ['iwlist', wireless_iface, 'scan']
            process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            stdout, stderr = process.communicate()
            
            if process.returncode != 0:
                return jsonify({'error': f'WiFi scanning failed: {stderr.decode()}'}), 500
            
            # 解析iwlist输出
            wifi_list = []
            current_network = {}
            for line in stdout.decode().split('\n'):
                line = line.strip()
                ssid_match = re.search(r'ESSID:"([^"]*)"', line)
                if ssid_match:
                    if current_network and 'ssid' in current_network:
                        wifi_list.append(current_network)
                    current_network = {'ssid': ssid_match.group(1), 'signal': 0, 'security': ''}
                    
                signal_match = re.search(r'Quality=(\d+)/(\d+)', line)
                if signal_match and current_network:
                    quality = int(signal_match.group(1)) / int(signal_match.group(2)) * 100
                    current_network['signal'] = int(quality)
                    
                if 'WPA2' in line and current_network:
                    current_network['security'] = 'WPA2'
                elif 'WPA' in line and current_network and 'security' not in current_network:
                    current_network['security'] = 'WPA'
                elif 'WEP' in line and current_network and 'security' not in current_network:
                    current_network['security'] = 'WEP'
            
            if current_network and 'ssid' in current_network:
                wifi_list.append(current_network)
        else:
            # 解析nmcli输出
            wifi_list = []
            for line in stdout.decode().split('\n'):
                if not line:
                    continue
                parts = line.split(':')
                if len(parts) >= 3:
                    wifi_list.append({
                        'ssid': parts[0],
                        'signal': int(parts[1]) if parts[1].isdigit() else 0,
                        'security': parts[2] if parts[2] else 'open'
                    })
        
        # 过滤重复的SSID，保留信号最强的
        filtered_list = {}
        for network in wifi_list:
            ssid = network['ssid']
            if not ssid:  # 忽略空SSID
                continue
                
            if ssid not in filtered_list or network['signal'] > filtered_list[ssid]['signal']:
                filtered_list[ssid] = network
        
        # 按信号强度排序
        sorted_list = sorted(filtered_list.values(), key=lambda x: x['signal'], reverse=True)
        
        return jsonify({'networks': sorted_list, 'count': len(sorted_list)})
        
    except Exception as e:
        SystemLog.log("ERROR", "network", f"扫描WiFi失败: {str(e)}")
        return jsonify({'error': str(e)}), 500

@network_bp.route('/wifi/connect', methods=['POST'])
def connect_wifi():
    """连接WiFi网络"""
    try:
        data = request.get_json()
        if not data:
            return jsonify({'error': 'Missing JSON data'}), 400
            
        ssid = data.get('ssid')
        password = data.get('password')
        
        if not ssid:
            return jsonify({'error': 'SSID is required'}), 400
        
        # 使用nmcli连接WiFi
        if password:
            cmd = ['nmcli', 'device', 'wifi', 'connect', ssid, 'password', password]
        else:
            cmd = ['nmcli', 'device', 'wifi', 'connect', ssid]
            
        process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        stdout, stderr = process.communicate()
        
        if process.returncode == 0:
            SystemLog.log("INFO", "network", f"成功连接到WiFi: {ssid}")
            return jsonify({'success': True, 'message': f'Connected to {ssid}'})
        else:
            error_msg = stderr.decode()
            SystemLog.log("ERROR", "network", f"连接WiFi失败: {error_msg}")
            return jsonify({'error': f'Connection failed: {error_msg}'}), 500
            
    except Exception as e:
        SystemLog.log("ERROR", "network", f"连接WiFi失败: {str(e)}")
        return jsonify({'error': str(e)}), 500

@network_bp.route('/wifi/disconnect', methods=['DELETE'])
def disconnect_wifi():
    """断开WiFi连接"""
    try:
        # 获取当前WiFi连接
        cmd = ['nmcli', '-t', '-f', 'NAME,TYPE,DEVICE', 'connection', 'show', '--active']
        process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        stdout, stderr = process.communicate()
        
        if process.returncode != 0:
            return jsonify({'error': 'Failed to get active connections'}), 500
        
        # 找到WiFi连接
        wifi_connection = None
        for line in stdout.decode().split('\n'):
            if not line:
                continue
            parts = line.split(':')
            if len(parts) >= 2 and 'wifi' in parts[1].lower():
                wifi_connection = parts[0]
                break
        
        if not wifi_connection:
            return jsonify({'error': 'No active WiFi connection found'}), 404
        
        # 断开连接
        cmd = ['nmcli', 'connection', 'down', wifi_connection]
        process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        stdout, stderr = process.communicate()
        
        if process.returncode == 0:
            SystemLog.log("INFO", "network", f"WiFi连接已断开: {wifi_connection}")
            return jsonify({'success': True, 'message': 'WiFi disconnected'})
        else:
            error_msg = stderr.decode()
            SystemLog.log("ERROR", "network", f"断开WiFi失败: {error_msg}")
            return jsonify({'error': error_msg}), 500
            
    except Exception as e:
        SystemLog.log("ERROR", "network", f"断开WiFi失败: {str(e)}")
        return jsonify({'error': str(e)}), 500

@network_bp.route('/settings', methods=['GET'])
def get_network_status():
    """获取当前网络状态和设置"""
    try:
        active_iface = None
        gateways = netifaces.gateways()
        default_gateway_info = gateways.get('default', {}).get(netifaces.AF_INET)

        if not default_gateway_info:
            return jsonify({'data': {'ip': 'N/A', 'type': 'disconnected'}})

        active_iface_name = default_gateway_info[1]
        addrs = netifaces.ifaddresses(active_iface_name)
        
        ip_info = addrs.get(netifaces.AF_INET, [{}])[0]
        
        # 确定连接类型
        conn_type = 'unknown'
        if active_iface_name.startswith('wlan') or active_iface_name.startswith('wlp'):
            conn_type = 'wifi'
        elif active_iface_name.startswith('eth') or active_iface_name.startswith('enp'):
            conn_type = 'ethernet'

        # 获取DNS服务器
        dns_servers = []
        try:
            with open('/etc/resolv.conf', 'r') as f:
                for line in f:
                    if line.startswith('nameserver'):
                        dns_servers.append(line.split()[1])
        except Exception:
            dns_servers.append('N/A')

        status = {
            'type': conn_type,
            'interface': active_iface_name,
            'ip': ip_info.get('addr', 'N/A'),
            'subnet': ip_info.get('netmask', 'N/A'),
            'gateway': default_gateway_info[0],
            'dns': dns_servers,
            'wifi_ssid': None
        }

        # 如果是WiFi，尝试获取SSID
        if conn_type == 'wifi':
            try:
                ssid_cmd = ['iwgetid', '-r', active_iface_name]
                ssid_process = subprocess.Popen(ssid_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
                ssid_stdout, _ = ssid_process.communicate()
                if ssid_process.returncode == 0:
                    status['wifi_ssid'] = ssid_stdout.decode().strip()
            except Exception as e:
                current_app.logger.warning(f"无法获取WiFi SSID: {e}")

        return jsonify({'data': status})
        
    except Exception as e:
        current_app.logger.error(f"获取网络状态失败: {str(e)}")
        return jsonify({'error': str(e)}), 500 